﻿using Transformable_Engine_v2.Engine.Helper;

namespace Transformable_Engine_v2.Engine.Graphics
{
    public class Color
    {
        #region X11 predefined colors

        //Pink colors
        public static Color Pink { get { return new Color(255, 192, 203); } }
        public static Color LightPink { get { return new Color(255, 182, 193); } }
        public static Color HotPink { get { return new Color(255, 105, 180); } }
        public static Color DeepPink { get { return new Color(255, 20, 147); } }
        public static Color PaleVioletRed { get { return new Color(219, 112, 147); } }
        public static Color MediumVioletRed { get { return new Color(199, 21, 133); } }

        //Red colors
        public static Color LightSalmon { get { return new Color(255, 160, 122); } }
        public static Color Salmon { get { return new Color(250, 128, 114); } }
        public static Color DarkSalmon { get { return new Color(233, 150, 122); } }
        public static Color LightCoral { get { return new Color(240, 128, 128); } }
        public static Color IndianRed { get { return new Color(205, 92, 92); } }
        public static Color Crimson { get { return new Color(220, 20, 60); } }
        public static Color FireBrick { get { return new Color(178, 34, 34); } }
        public static Color DarkRed { get { return new Color(139, 0, 0); } }
        public static Color Red { get { return new Color(255, 0, 0); } }

        //Orange colors
        public static Color OrangeRed { get { return new Color(255, 69, 0); } }
        public static Color Tomato { get { return new Color(255, 99, 71); } }
        public static Color Coral { get { return new Color(255, 127, 80); } }
        public static Color DarkOrange { get { return new Color(255, 140, 0); } }
        public static Color Orange { get { return new Color(255, 165, 0); } }
        public static Color Gold { get { return new Color(255, 215, 0); } }

        //Yellow colors
        public static Color Yellow { get { return new Color(255, 255, 0); } }
        public static Color LightYellow { get { return new Color(255, 255, 224); } }
        public static Color LemonChiffon { get { return new Color(255, 250, 205); } }
        public static Color LightGoldenrodYellow { get { return new Color(250, 250, 210); } }
        public static Color PapayaWhip { get { return new Color(255, 239, 213); } }
        public static Color Moccasin { get { return new Color(255, 228, 181); } }
        public static Color PeachPuff { get { return new Color(255, 218, 185); } }
        public static Color PaleGoldenrod { get { return new Color(238, 232, 170); } }
        public static Color Khaki { get { return new Color(240, 230, 140); } }
        public static Color DarkKhaki { get { return new Color(189, 183, 107); } }

        //Brown colors
        public static Color Cornsilk { get { return new Color(255, 248, 220); } }
        public static Color BlanchedAlmond { get { return new Color(255, 235, 205); } }
        public static Color Bisque { get { return new Color(255, 228, 196); } }
        public static Color NavajoWhite { get { return new Color(255, 222, 173); } }
        public static Color Wheat { get { return new Color(245, 222, 179); } }
        public static Color BurlyWood { get { return new Color(222, 184, 135); } }
        public static Color Tan { get { return new Color(210, 180, 140); } }
        public static Color RosyBrown { get { return new Color(188, 143, 143); } }
        public static Color SandyBrown { get { return new Color(244, 164, 96); } }
        public static Color Goldenrod { get { return new Color(218, 165, 32); } }
        public static Color DarkGoldenrod { get { return new Color(184, 134, 11); } }
        public static Color Peru { get { return new Color(205, 133, 63); } }
        public static Color Chocolate { get { return new Color(210, 105, 30); } }
        public static Color SaddleBrown { get { return new Color(139, 69, 19); } }
        public static Color Sienna { get { return new Color(160, 82, 45); } }
        public static Color Brown { get { return new Color(165, 42, 42); } }
        public static Color Maroon { get { return new Color(128, 0, 0); } }

        //Green colors
        public static Color DarkOliveGreen { get { return new Color(85, 107, 47); } }
        public static Color Olive { get { return new Color(128, 128, 0); } }
        public static Color OliveDrab { get { return new Color(107, 142, 35); } }
        public static Color YellowGreen { get { return new Color(154, 205, 50); } }
        public static Color LimeGreen { get { return new Color(50, 205, 50); } }
        public static Color Lime { get { return new Color(0, 255, 0); } }
        public static Color LawnGreen { get { return new Color(124, 252, 0); } }
        public static Color Chartreuse { get { return new Color(127, 255, 0); } }
        public static Color GreenYellow { get { return new Color(173, 255, 47); } }
        public static Color SpringGreen { get { return new Color(0, 255, 127); } }
        public static Color MediumSpringGreen { get { return new Color(0, 250, 154); } }
        public static Color LightGreen { get { return new Color(144, 238, 144); } }
        public static Color PaleGreen { get { return new Color(152, 251, 152); } }
        public static Color DarkSeaGreen { get { return new Color(143, 188, 143); } }
        public static Color MediumSeaGreen { get { return new Color(60, 179, 113); } }
        public static Color SeaGreen { get { return new Color(46, 139, 87); } }
        public static Color ForestGreen { get { return new Color(34, 139, 34); } }
        public static Color Green { get { return new Color(0, 128, 0); } }
        public static Color DarkGreen { get { return new Color(0, 100, 0); } }

        //Cyan colors
        public static Color MediumAquamarine { get { return new Color(102, 205, 170); } }
        public static Color Aqua { get { return new Color(0, 255, 255); } }
        public static Color Cyan { get { return new Color(0, 255, 255); } }
        public static Color LightCyan { get { return new Color(224, 255, 255); } }
        public static Color PaleTurquoise { get { return new Color(175, 238, 238); } }
        public static Color Aquamarine { get { return new Color(127, 255, 212); } }
        public static Color Turquoise { get { return new Color(64, 224, 208); } }
        public static Color MediumTurquoise { get { return new Color(72, 209, 204); } }
        public static Color DarkTurquoise { get { return new Color(0, 206, 209); } }
        public static Color LightSeaGreen { get { return new Color(32, 178, 170); } }
        public static Color CadetBlue { get { return new Color(95, 158, 160); } }
        public static Color DarkCyan { get { return new Color(0, 139, 139); } }
        public static Color Teal { get { return new Color(0, 128, 128); } }

        //Blue colors
        public static Color LightSteelBlue { get { return new Color(176, 196, 222); } }
        public static Color PowderBlue { get { return new Color(176, 224, 230); } }
        public static Color LightBlue { get { return new Color(173, 216, 230); } }
        public static Color SkyBlue { get { return new Color(135, 206, 235); } }
        public static Color LightSkyBlue { get { return new Color(135, 206, 250); } }
        public static Color DeepSkyBlue { get { return new Color(0, 191, 255); } }
        public static Color DodgerBlue { get { return new Color(30, 144, 255); } }
        public static Color CornflowerBlue { get { return new Color(100, 149, 137); } }
        public static Color SteelBlue { get { return new Color(70, 130, 180); } }
        public static Color RoyalBlue { get { return new Color(65, 105, 225); } }
        public static Color Blue { get { return new Color(0, 0, 255); } }
        public static Color MediumBlue { get { return new Color(0, 0, 205); } }
        public static Color DarkBlue { get { return new Color(0, 0, 139); } }
        public static Color Navy { get { return new Color(0, 0, 128); } }
        public static Color MidnightBlue { get { return new Color(25, 25, 112); } }

        //Purple colors
        public static Color Lavender { get { return new Color(230, 230, 250); } }
        public static Color Thistle { get { return new Color(216, 191, 216); } }
        public static Color Plum { get { return new Color(221, 160, 221); } }
        public static Color Violet { get { return new Color(238, 130, 238); } }
        public static Color Orchid { get { return new Color(218, 112, 214); } }
        public static Color Fuschia { get { return new Color(255, 0, 255); } }
        public static Color Magenta { get { return new Color(255, 0, 255); } }
        public static Color MediumOrchid { get { return new Color(186, 85, 211); } }
        public static Color MediumPurple { get { return new Color(147, 112, 219); } }
        public static Color BlueViolet { get { return new Color(138, 43, 226); } }
        public static Color DarkViolet { get { return new Color(148, 0, 211); } }
        public static Color DarkOrchid { get { return new Color(153, 50, 204); } }
        public static Color DarkMagenta { get { return new Color(139, 0, 139); } }
        public static Color Purple { get { return new Color(128, 0, 128); } }
        public static Color Indigo { get { return new Color(75, 0, 130); } }
        public static Color DarkSlateBlue { get { return new Color(72, 61, 139); } }
        public static Color SlateBlue { get { return new Color(106, 90, 205); } }
        public static Color MediumSlateBlue { get { return new Color(123, 104, 238); } }

        //Gray colors
        public static Color Gainsboro { get { return new Color(220, 220, 220); } }
        public static Color LightGray { get { return new Color(211, 211, 211); } }
        public static Color Silver { get { return new Color(192, 192, 192); } }
        public static Color DarkGray { get { return new Color(169, 169, 169); } }
        public static Color Gray { get { return new Color(128, 128, 128); } }
        public static Color DimGray { get { return new Color(105, 105, 105); } }
        public static Color LightSlateGray { get { return new Color(119, 136, 153); } }
        public static Color SlateGray { get { return new Color(112, 128, 144); } }
        public static Color DarkSlateGray { get { return new Color(47, 79, 79); } }
        public static Color Black { get { return new Color(0, 0, 0); } }
        public static Color White { get { return new Color(255, 255, 255); } }
        public static Color Transparent { get { return new Color(0, 0, 0, 0); } }
        #endregion

        /// <summary>
        /// Red channel of the color
        /// </summary>
        public double R { get; set; }

        /// <summary>
        /// Green channel of the color
        /// </summary>
        public double G { get; set; }

        /// <summary>
        /// Blue channel of the color
        /// </summary>
        public double B { get; set; }

        /// <summary>
        /// Alpha channel of the color
        /// </summary>
        public double A { get; set; }

        /// <summary>
        /// Creates a new instance of the Color class
        /// </summary>
        public Color() :
            this(0, 0, 0)
        {
            
        }

        /// <summary>
        /// Creates a new instance of the Color class
        /// </summary>
        /// <param name="c">Color to copy</param>
        public Color(Color c) :
            this(c.R, c.G, c.B, c.A)
        {

        }

        /// <summary>
        /// Creates a new instance of the Color class
        /// </summary>
        /// <param name="c">Color to copy</param>
        /// <param name="alpha">Alpha channel to use</param>
        public Color(Color c, float alpha) :
            this(c.R, c.G, c.B, alpha)
        {

        }

        /// <summary>
        /// Creates a new instance of the Color class
        /// </summary>
        /// <param name="r">Red component</param>
        /// <param name="g">Green component</param>
        /// <param name="b">Blue component</param>
        /// <param name="a">Alpha component</param>
        public Color(double r, double g, double b, double a = 255)
        {
            R = r;
            G = g;
            B = b;
            A = a;
        }


        /// <summary>
        /// Returns the same color, but fully transparent
        /// </summary>
        /// <returns>Transparent color</returns>
        public Color ToTransparentColor()
        {
            return new Color(R, G, B, 0);
        }

        /// <summary>
        /// Converts to a SFML native color type
        /// </summary>
        /// <returns>SFML native color type</returns>
        public SFML.Graphics.Color ToSFMLColor()
        {
            return new SFML.Graphics.Color((byte) R, (byte) G, (byte) B, (byte) A);
        }

        /// <summary>
        /// Operator overload to substract two colors
        /// </summary>
        /// <param name="color1">Color to substract</param>
        /// <param name="color2">Color to substract</param>
        /// <returns>Resulting color</returns>
        public static Color operator -(Color color1, Color color2)
        {
            return new Color(color1.R - color2.R, color1.G - color2.G, color1.B - color2.B, color1.A - color2.A);
        }

        /// <summary>
        /// Operator overload to add two colors
        /// </summary>
        /// <param name="color1">Color to add</param>
        /// <param name="color2">Color to add</param>
        /// <returns>Resulting color</returns>
        public static Color operator +(Color color1, Color color2)
        {
            return new Color(color1.R + color2.R, color1.G + color2.G, color1.B + color2.B, color1.A + color2.A);
        }

        /// <summary>
        /// Operator overload multiply a color by a double
        /// </summary>
        /// <param name="color1">Color</param>
        /// <param name="multiplicant">Multiplicant</param>
        /// <returns>Resulting color</returns>
        public static Color operator *(Color color1, double multiplicant)
        {
            return new Color(color1.R * multiplicant, 
                            color1.G * multiplicant, 
                            color1.B * multiplicant, 
                            color1.A * multiplicant);
        }

        /// <summary>
        /// Operator overload multiply a color by a double
        /// </summary>
        /// <param name="color1">Color</param>
        /// <param name="multiplicant">Multiplicant</param>
        /// <returns>Resulting color</returns>
        public static Color operator *(double multiplicant, Color color1)
        {
            return color1*multiplicant;
        }

        /// <summary>
        /// Operator overload which inverts the color
        /// </summary>
        /// <param name="color">Color to invert</param>
        /// <returns>Inverted color</returns>
        public static Color operator -(Color color)
        {
            return new Color(255 - color.R, 255 - color.G, 255 - color.B, color.A);
        }

        public override string ToString()
        {
            return string.Format("[{0}, {1}, {2}, {3}]", R, G, B, A);
        }

        public void Clamp()
        {
            R = R.Clamp(0, 255);
            G = G.Clamp(0, 255);
            B = B.Clamp(0, 255);
            A = A.Clamp(0, 255);
        }
    }
}